package com.zh.junit;

import com.zh.junit.func.DemoCase;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;

import java.time.Duration;

/**
 * Junit的常用注解的使用
 */
public class AppJunitApi {

    /*
    BeforeAll 类级别装载：在整个测试执行周期中只调用一次（声明static）
     */
    @BeforeAll
    static void beforeAll() {
        System.out.println("@BeforeAll ...");
    }

    /*
    AfterAll 类级别卸载：在整个测试执行周期中只调用一次（声明static）
     */
    @AfterAll
    public static void afterAll() {
        System.out.println("@AfterAll ...");
    }

    /*
    BeforeEach 方法级装载： 每个测试实例都调用一次
     */
    @BeforeEach
    public void beforeEach() {
        System.out.println("@BeforeEach ...");
    }

    /*
    AfterEach 方法级装载： 每个测试实例都调用一次
     */
    @AfterEach
    public void afterEach() {
        System.out.println("@AfterEach ...");
    }

    /*
    测试方法执行：一个@Test代表一个测试实例
     */
    @Test
    public void findById() {
        System.out.println("findById ...");
        Assertions.assertEquals(2, 2);
    }

    /*
     测试方法执行：一个@Test代表一个测试实例
     */
    @Test
    public void findList() {
        System.out.println("findList ...");
        Assertions.assertEquals(2, 2, "error message");
    }

    /*
    分组断言，执行分组中所有断言，分组中任何一个断言错误都会一起报告
     */
    @Test
    void groupAssertions() {
        //分成两个组
        Assertions.assertAll("person"
                , () -> {
                    Assertions.assertEquals("John", "John");
                    Assertions.assertEquals(2, 2);
                }
                , () -> {
                    Assertions.assertEquals("Doe", "Doe");
                    Assertions.assertEquals(2, 2);
                }
        );
    }

    /*
    超时断言
     */
    @Test
    void timeoutNotExceeded() {
        // 断言超时，完成任务小于2分钟时，测试通过
        Assertions.assertTimeout(Duration.ofMinutes(2), () -> {
            System.out.println("完成任务小于2分钟时，测试通过");
        });
    }

    @Test
    void timeoutExceeded() {
        // 断言超时，会在任务执行完毕后才返回断言失败，也就是1000毫秒后返回结果
        Assertions.assertTimeout(Duration.ofMillis(10), () -> {
            // 执行任务花费时间1000毫秒
            Thread.sleep(1000);
        });

        // 断言超时，任务超时会立即返回断言失败，也就是10毫秒后返回结果
        Assertions.assertTimeoutPreemptively(Duration.ofMillis(10), () -> {
            Thread.sleep(1000);
        });
    }

    @DisplayName("参数化测试")
    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3})
    void paramTest(int a) {
        Assertions.assertTrue(a > 0 && a < 4);
    }

    @DisplayName("条件覆盖示例1") //用例的标题
    @ParameterizedTest //参数化测试
    @CsvSource({"1,2,3", "1,1,3"}) //参数值
    public void shouldAnswerWithTrue(int a, int b, int c) {
        DemoCase demoCase = new DemoCase();

        boolean success = demoCase.coverageCase(a, b, c);
        Assertions.assertTrue(success);
    }

    @Disabled
    @DisplayName("测试两数相除")
    @Test
    public void disabledTest() {
        int a = 1;
        int b = 0;
        double result = a / b;
        System.out.println(result);
    }

    /*
    重复测试
     */
    //自定义重复测试的显示名称
    @RepeatedTest(value = 10, name = "{displayName} ===> {currentRepetition}/{totalRepetitions}")
    @DisplayName("repeatTest")
    void repeatedTest(TestInfo testInfo, RepetitionInfo repetitionInfo) {
        //我们可以通过TestInfo在测试中获取测试的相关信息，比如输出自定义的测试名
        System.out.println(testInfo.getDisplayName());
        //输出当前重复次数
        System.out.println("currentRepetition:" + repetitionInfo.getCurrentRepetition());

    }
}
